package com.wewins.fota.service.export;

import com.wewins.fota.bean.bo.excel.DataSource;
import com.wewins.fota.bean.bo.excel.ExcelHeaderItem;
import com.wewins.fota.bean.bo.excel.ExportData;
import com.wewins.fota.bean.bo.excel.RowData;
import com.wewins.fota.bean.bo.excel.column.ExcelColumn;
import com.wewins.fota.bean.bo.excel.column.ExcelColumnGroup;
import com.wewins.fota.common.constant.FotaCode;
import com.wewins.fota.common.util.ExcelUtil;
import com.wewins.fota.service.ExportService;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public interface ExportModel {
    default <T> ExportModel fill(List<T> data) {
        this.fillDataAfter(this.fillData(data));
        return this;
    }

    <T> List<DataSource> fillData(List<T> data);

    default void fillDataAfter(List<DataSource> data) {
        List<RowData> rows = data.stream()
                .map(DataSource::convertColumnData)
                .filter(item -> item.getColumns().size() > 0)
                .collect(Collectors.toList());
        this.setData(ExportData.builder()
                .headers(this.getHeaders())
                .rows(rows)
                .build()
        );
    }

    List<ExcelHeaderItem> getHeaders();

    String getPath();

    ExportData getData();

    void setData(ExportData data);

    default <T> List<ExcelHeaderItem> getHeaders(Class<T> clazz) {
        ArrayList<ExcelHeaderItem> headers = new ArrayList<>();
        Queue<Class<T>> tmpQueue = new LinkedList<>();
        tmpQueue.add(clazz);
        while (!tmpQueue.isEmpty()) {
            ArrayList<ExcelHeaderItem> tmpHeaders = new ArrayList<>();
            Class<T> tmp = tmpQueue.poll();
            Stream.of(tmp.getDeclaredFields()).forEach(
                    item -> {
                        ExcelColumnGroup columnGroup = item.getAnnotation(ExcelColumnGroup.class);
                        if (columnGroup != null) {
                            tmpQueue.add((Class<T>) item.getType());
                            return;
                        }
                        ExcelColumn column = item.getAnnotation(ExcelColumn.class);
                        if (column != null) {
                            ExcelHeaderItem head = ExcelHeaderItem.builder().fieldName(item.getName())
                                    .name(column.value())
                                    .width(column.width())
                                    .cellClazz(column.cellClazz())
                                    .build();
                            tmpHeaders.add(head);
                        }
                    }
            );
            headers.addAll(0, tmpHeaders);
        }
        return headers;
    }

    default void write() throws IOException {
        ExcelUtil.builder(this.getPath()).writeWithAdd(this.getData());
    }

    static ExportModel getExportModel(int type, String filePath, ExportService service) {
        ExportModel model;
        if (type == FotaCode.EXPORT_4_YTL.getCode()) {
            model = ExportFotaLog2Model.builder().path(filePath).service(service).build();
        } else {
            model = ExportFotaLogModel.builder().path(filePath).service(service).build();
        }
        return model;
    }
}
